<template>
  <div>
    <NuxtLayout name="default">
      <template #mainLeft>
        <div
            class="h-full w-[400px] flex flex-col bg-white"
            style="border-radius: 15px 0 0 15px"
        >
          <div class="flex p-[20px]">
            <div class="text-lg font-medium line-clamp-1 mr-auto">
              {{ modelData.name }}
            </div>
           <!-- <ElButton link type="primary" @click="insertExample"
            >插入示例</ElButton
            >-->
          </div>
          <div class="flex-1 min-h-0">
            <ElScrollbar>
              <div class="p-[20px]">
                <FormDesigner
                    ref="formDesignerRef"
                    v-model="formData"
                    :form-lists="modelData.form"
                    size="large"
                />
              </div>
            </ElScrollbar>
          </div>

          <div class="px-[20px] pb-[20px]">
            <!--模型选择-->
            <!--<ModelPicker
                :is-create="true"
                v-model="chatModel"
                v-model:model="chatModelConfig"
            ></ModelPicker>-->
            <!--立即生成-->
            <div class="flex flex-col justify-center items-center">
              <ElButton
                  class="create-btn"
                  @click="handleCreate"
                  :loading="isReceiving"
              >
                立即生成
                <span v-html="getCountMsg" class="text-xs ml-2" />
              </ElButton>
            </div>
          </div>
        </div>
      </template>
      <div class="h-full flex">
        <ChattingChattingv1
            ref="chattingRef"
            v-model:model="chatParams.model"
            v-model:network="chatParams.network"
            v-model:plugin="plugins"
            :content-list="chatContentList"
            :send-disabled="isReceiving"
            :selectval="sessionActive"
            :avatar="appStore.config.chat.chat_logo"
            :currentId="currentId"
            :chat-type="1"
            @close="chatClose"
            @content-post="contentPost"
            @clean-chat-log="cleanChatLog"
            @top="handleTop"
            @addMsg="addMsg"
        >
          <div
              v-show="hasMoreDialogueRecords && userStore.isLogin"
              class="h-[40px] py-[10px] text-[#999] text-center cursor-pointer"
              @click.stop="handleTop"
          >
            <template
                v-if="hasMoreDialogueRecords && userStore.isLogin"
            >
              {{
                dialogueRecordsLoading
                    ? '正在加载中...'
                    : '-- 点击加载 --'
              }}
            </template>
          </div>
          <div v-if="!chatContentList.length" class="px-[50px]">
            <div
                class="my-[60px] text-center text-[30px] font-medium color"
            >
              你好，我是{{ modelData.name }}
            </div>
          </div>
        </ChattingChattingv1>
        <el-dialog v-model="dialogTableVisible" title="历史记录" width="800">
          <TheSessionv1 @updateHide="updateHide"/>
        </el-dialog>
      </div>
      <TheGuidedPopup ref="guidedPopupRef" />
    </NuxtLayout>
  </div>
</template>
<script setup lang="ts">
import { getchatLog, samplesLists, cleanChat, chatSendText } from '@/api/chat'
import { useUserStore } from '~~/stores/user'
import feedback from '~~/utils/feedback'
import {ElMessageBox, ElScrollbar} from 'element-plus'
import { useAppStore } from '~/stores/app'
import { isNewDay } from '~/utils/validate'
const formData = ref<any>({})
import {CHAT_LIMIT_KEY, CHAT_MODEL_KEY, PLUGIN_MODEL_KEY} from '~/enums/cacheEnums'
import { watch } from 'vue'
const formDesignerRef = shallowRef()
import TheSessionv1 from '@/components/the-session/indexv1.vue'
import ModelPicker from "~/components/chatting/model-picker.vue";
import {getCreationDetail} from "~/api/create";
import {cloneDeep} from "lodash-es";
const userStore = useUserStore()
const appStore = useAppStore()
const router = useRouter()
const route = useRoute()
const currentId = ref(Number(route.query.id))
const scrollbarRef = ref<InstanceType<typeof ElScrollbar>>(null)
const currentCreationHistory = ref<any[]>([])
//对话记录列表
const dialogTableVisible = ref(false)
//对话框ref
const chattingRef = ref(null)
const guidedPopupRef = shallowRef()
// 聊天次数(消耗
const chatModelConfig = ref({
  balance: 1,
  member_free: false
})
const chatModel = ref<string>('')
const chatParams = reactive({
  model: '',
  network: false
})

const plugins = reactive({
  type: '',
  id: '',
  file: {} as any
})

const updateHide = () => {
  dialogTableVisible.value = false
}

const insertExample = () => {
  modelData.value?.form.forEach((item: any) => {
    if (item.props.placeholder && !item.props.defaultValue) {

      formData.value[item.id] = item.props.placeholder
    }
  })
}

const strmx = ref<any>({})


const setFormDataDefault = () => {
  modelData.value?.form.forEach((item: any) => {
    if (item.props.defaultValue) {
      formData.value[item.id] = cloneDeep(item.props.defaultValue)
    } else {
      formData.value[item.id] = undefined
    }
  })
}

const getCountMsg = computed(() => {
  if (!chatModelConfig.value.key) return ''
  if (!chatModelConfig.value.member_free) {
    if (chatModelConfig.value.balance) {
      return `消耗 ${chatModelConfig.value.balance} 条对话`
    } else {
      return '免费'
    }
  } else {
    return '会员免费'
  }
})

const resetPluginData = () => {
  plugins.file = { url: '' }
}


const handleCreate = async () => {

  try {
    await formDesignerRef.value?.validate()
  } catch (error) {
    feedback.msgError('必填项不能为空')
    return
  }
  if (userStore.userInfo.is_chat_limit && isNewDay(true, CHAT_LIMIT_KEY)) {
    try {
      await ElMessageBox.confirm(
          '已超过会员对话上限次数，继续对话将会消耗账户的对话余额',
          '对话上限提示',
          {
            showClose: false,
            confirmButtonText: '继续',
            cancelButtonText: '关闭'
          }
      )
    } catch (e) {
      return
    }
  }

  // 保存聊天模型（用于刷新之后还能记住当前聊天模型
  const model = useCookie(CHAT_MODEL_KEY)
  model.value = chatModel.value
  let str = ''
  for (const key in modelData.value.form) {
    let id = modelData.value.form[key].id
    let value = formData.value[id]? formData.value[id] : ''
    str += `${modelData.value.form[key].props.title}:${value} `
  }
  contentPost(formData.value,0,str)

}

const { data: modelData, refresh: modelApiRefresh } = await useAsyncData(
    () =>
        getCreationDetail({
          id: currentId.value
        }),
    {
      default() {
        return {}
      },
      transform(data) {
        if (!data.form) {
          data.form = defaultForm
        }
        return data
      }
    }
)

watch(
    () => plugins.id,
    (val) => {
      if (val == 'gpt-4-all') {
        resetPluginData()
      }
    }
)
const {
  sessionActive,
  sessionAdd,
  currentSession,
  sessionEdit,
  getSessionLists
} = await useSessionList()

setTimeout(function (){
  useAsyncData(() => getSessionLists(2, currentId.value), {
    default() {
      return []
    },
    immediate: true
  })
},500)

const addMsg = (index?: number) => {
  dialogTableVisible.value = true
}

const chatContentList = ref<any[]>([])
const chatLogParams = reactive({
  type: 1,
  //category_id: sessionActive.value,
  page_type: 1,
  page_no: 1,
  page_size: 15
})
const hasMoreDialogueRecords = ref<boolean>(false)
const dialogueRecordsLoading = ref<boolean>(false)

/**
 * 1.上拉加载
 * 2.切换分类时重制上拉
 * 3.对话以后加载(最新一条就行)
 * flag = 1的时候表示对话结束了，获取最新一条数据
 **/
let contentListHeight = 0 // 旧记录高度，新记录高度 - 旧记录高度得到最新刷新定位位置
//获取聊天记录
const getChatList = async (flag?: boolean) => {
  dialogueRecordsLoading.value = true
  hasMoreDialogueRecords.value = true
  try {
    const chatElement = document.getElementsByClassName('contentList')[0]
    const data = await getchatLog({
      ...chatLogParams,
      page_no: flag ? 1 : chatLogParams.page_no,
      page_size: flag ? 1 : chatLogParams.page_size
    })

    const { page_no, page_size } = chatLogParams
    if (
        page_no * page_size > data.count ||
        chatContentList.value.length / 2 >= data.count
    ) {
      hasMoreDialogueRecords.value = false
    }

    const transformData = data.lists.map((item: any) => {
      if (item.type == 1) {
        return { ...item, from_avatar: userStore.userInfo.avatar }
      } else {
        return {
          ...item,
          from_avatar: appStore.config.chat.chat_logo
        }
      }
    })

    if (flag) {
      chatContentList.value.splice(-2, 2)
      chatContentList.value = [...chatContentList.value, ...transformData]
    } else {
      chatContentList.value = [...transformData, ...chatContentList.value]
    }

    // 刷新记录时将滚动条定位到刷新之前的元素那里
    await nextTick()
    if (currentSession.value == '新的会话') {
      chatContentList.value = []
      return
    }
    const rect = Object.freeze(chatElement?.getBoundingClientRect())
    if (rect && contentListHeight) {
      chattingRef.value?.scrollTo(rect.height - contentListHeight)
    }
    contentListHeight = rect.height
  } catch (e) {
    console.log('聊天记录错误', e)
  } finally {
    dialogueRecordsLoading.value = false
  }
}

const handleTop = () => {
  if (hasMoreDialogueRecords.value && contentListHeight) {
    chatLogParams.page_no += 1
    getChatList()
  }
}

const { pauseAll } = useAudioPlay()
const isReceiving = ref(false)
const newUserInput = ref<string>('')
//发送问题
const contentPost = async (userInput: any,type = 0,str = '') => {
  if (!userStore.isLogin) return userStore.toggleShowLogin(true)
  if (isReceiving.value) return
  isReceiving.value = true
  if (userStore.userInfo.is_chat_limit && isNewDay(true, CHAT_LIMIT_KEY)) {
    try {
      await ElMessageBox.confirm(
          '已超过会员对话上限次数，继续对话将会消耗账户的对话余额',
          '对话上限提示',
          {
            showClose: false,
            confirmButtonText: '继续',
            cancelButtonText: '关闭'
          }
      )
    } catch (e) {
      isReceiving.value = false
      return
    }
  }

  if (sessionActive.value === -1||sessionActive.value === 0) {
    await sessionAdd(2,currentId.value)
  }
  if (currentSession.value === '新的会话') {

    await sessionEdit(sessionActive.value, str)
  }
  newUserInput.value = userInput
  chatContentList.value.push({
    type: 1,
    content: userInput,
    from_avatar: userStore.userInfo.avatar,
    file_url: plugins.file.url,
    file_name: plugins.file.name,
    file_type: plugins.type == '' ? 0 : plugins.type == 'image' ? 1 : 2
  })
  const result = reactive({
    type: 2,
    loading: true,
    content: [],
    create_time: ' ',
    from_avatar: appStore.config.chat.chat_logo,
    id: ''
  })
  chatContentList.value.push(result)

  // 缓存使用的插件id
  const pluginId = useCookie(PLUGIN_MODEL_KEY)
  pluginId.value = plugins.id

  try {
    await chatSendText(
        {
          question: userInput,
          type: 2,
          other_id: currentId.value,
          category_id: sessionActive.value,
          ...chatParams,
          model: plugins.id ? plugins.id : chatParams.model,
          file: plugins.file.url,
          is_custom_dialogue:0,
          is_immediately:type==0?1:0
        },
        {
          onstart(reader) {
            streamReader = reader
            pauseAll()
          },
          onmessage(value) {
            value
                .trim()
                .split('data:')
                .forEach(async (text) => {
                  if (text !== '') {
                    try {
                      const dataJson = JSON.parse(text)
                      const {
                        id: chatId,
                        code,
                        event,
                        data,
                        index,
                        incremental
                      } = dataJson
                      if (event == 'error' && code === 101) {
                        guidedPopupRef.value?.open()
                      } else if (event == 'error') {
                        feedback.msgError(data)
                        chattingRef.value.setInput(
                            newUserInput.value
                        )
                      }

                      if (data) {
                        if (!result.content[index]) {
                          result.content[index] = ''
                        }
                        result.content[index] = incremental
                            ? result.content[index] + data
                            : data
                      }

                      if (event === 'finish') {
                        result.loading = false
                        if (plugins.id == 'gpt-4-all') {
                          resetPluginData()
                        }
                        return
                      }
                    } catch (error) {}
                  }
                })
          },
          onclose() {
            isReceiving.value = false
            setTimeout(async () => {
              await getChatList(true)
              await nextTick()
              chattingRef.value.scrollToBottom()
            }, 600)
            userStore.getUser()
          }
        }
    )
  } catch (error) {
    console.log(error)
    isReceiving.value = false
    chattingRef.value.setInput(newUserInput.value)
    chatContentList.value.splice(chatContentList.value.length - 2, 2)
  }

  nextTick(() => {
    chattingRef.value.scrollToBottom()
  })
}

let streamReader: ReadableStreamDefaultReader<Uint8Array> | null = null
const chatClose = (index?: number) => {
  streamReader?.cancel()
  if (index) {
    chatContentList.value[index].loading = false
  }
  isReceiving.value = false
}

//清空会话
const cleanChatLog = async () => {
  console.log()
  await feedback.confirm('确定清空对话？')
  await cleanChat({ type: 1, category_id: sessionActive.value })
  chatContentList.value = []
}

onMounted(async () => {
  if (route.query.cid || route.query.user_sn) {
    const cid: any = useCookie('cid')
    const user_sn: any = useCookie('user_sn')
    cid.value = route.query.cid
    user_sn.value = route.query.user_sn
    await nextTick()
    userStore.checkShare()
  }
  await getChatList()
  await nextTick()
  chattingRef.value.scrollToBottom()
})
watch(sessionActive, async (v1) => {
  // 切换对话重置分页数据 Start
  chatLogParams.category_id = v1
  chatLogParams.page_no = 1
  chatContentList.value = []
  contentListHeight = 0
  // 切换对话重置分页数据 End
  chatClose()
  await getChatList()
  await nextTick()
  chattingRef.value.scrollToBottom()
})

definePageMeta({
  layout: false
})
</script>
<style lang="scss" scoped>
.container-tip {
  border: 1px solid #fb9a3b;
}
.item {
  :hover {
    color: #fb9a3b;
  }
}
</style>
